package zouhaotian.rbac.dao.file;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import zouhaotian.rbac.domain.entity.BaseEntity;
import zouhaotian.rbac.domain.entity.Dept;
import zouhaotian.rbac.domain.entity.Role;
import zouhaotian.rbac.domain.entity.User;
import zouhaotian.rbac.exception.FatalException;
import zouhaotian.rbac.exception.PersistenceException;


import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 持久化工具类-读写
 *
 * @auther 邹昊天
 * @since 2025/6/21 22:57
 */
public class PersistUtil {

    private static final Logger logger = LoggerFactory.getLogger(PersistUtil.class);

    private static final Path rootPath = Paths.get("./data");

    private static final Map<Class<? extends BaseEntity>, Path> dirMap = new HashMap<>();


    private static<T extends BaseEntity>Path getDir (Class<T> clazz)
    {
        if (!dirMap.containsKey(clazz))
        {
            Path dir =rootPath.resolve(clazz.getSimpleName().toLowerCase());
            try{
                Files.createDirectories(dir);
                dirMap.put(clazz,dir);
            }catch (IOException e)
            {
                logger.error("创建数据储存目录失败",e);
                throw new FatalException();
            }
        }
        return dirMap.get(clazz);
    }

    public static <T extends BaseEntity> boolean exists(Class<T> clazz,Integer id)
    {
        Path dir =getDir(clazz);
        Path file = dir.resolve(id.toString());
        return Files.exists(file);


    }

    public static <T extends BaseEntity> void  write(T obj)
    {
        Path dir =getDir(obj.getClass());
        Path file =dir.resolve(obj.getId().toString());
        try(ObjectOutputStream dos =new ObjectOutputStream(Files.newOutputStream(file)))
        {
            dos.writeObject(obj);
        }catch (IOException e)
        {
            logger.error("创建数据文件失败：数据类型:{},ID:{}",obj.getClass().getSimpleName(),obj.getId(),e);
            throw new PersistenceException(e);
        }
    }
    public static <T extends BaseEntity> T  read(Class<T> clazz,Integer id)
    {
        Path dir =getDir(clazz);
        Path file = dir.resolve(id.toString());
        try(ObjectInputStream dos =new ObjectInputStream(Files.newInputStream(file)))
        {
            return clazz.cast(dos.readObject());
        }catch (IOException | ClassNotFoundException e)
        {
            logger.error("读取数据文件失败：数据类型:{},ID:{}",clazz.getSimpleName(),id,e);
            throw new PersistenceException(e);
        }


    }
    public static <T extends BaseEntity> void delete(Class<T> clazz,Integer id)
    {
        Path dir =getDir(clazz);
        Path file = dir.resolve(id.toString());
        try
        {
            Files.delete(file);
        }catch (IOException  e)
        {
            logger.error("删除数据文件失败：数据类型:{},ID:{}",clazz.getSimpleName(),id,e);
            throw new PersistenceException(e);
        }
    }

    public static <T extends BaseEntity> List<T> listAll (Class<T> clazz)
    {
        Path dir =getDir(clazz);
        List<T>list=new ArrayList<>();
        try(DirectoryStream<Path> stream= Files.newDirectoryStream(dir))
        {
            for (Path entry:stream)
            {
                Integer id =Integer.parseInt(entry.getFileName().toString());
                list.add(read(clazz,id));
            }
            return list;
        }catch (IOException e)
        {
            logger.error("读取数据文件列表失败：数据类型:{},ID: {}",clazz.getSimpleName(),e);
            throw new PersistenceException(e);
        }


    }

    public static <T extends BaseEntity> List<String> listFileNames(Class<T> clazz) {
        Path dir = getDir(clazz);
        List<String> list = new ArrayList<>();
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
            for (Path entry : stream) {
                String fileName = entry.getFileName().toString();
                list.add(fileName);
            }
            return list;
        } catch (IOException e) {
            logger.error("读取数据文件列表失败：数据类型:{},ID: {}", clazz.getSimpleName(), e);
            throw new PersistenceException(e);
        }
    }

}



